﻿namespace SourceCodeRepository.Common.AOP
{
    using System;
    using Infra.Logging;
    using PostSharp.Laos;
    using StructureMap;

    /// <summary>
    /// Aspect based attribute used for Loging.
    /// </summary>
    [Serializable]
    public sealed class LogAttribute : OnMethodBoundaryAspect
    {
        private ILog _logger;

        /// <summary>
        /// Gets or sets the logger.
        /// </summary>
        /// <value>The logger.</value>
        private ILog Logger
        {
            get
            {
                if (_logger == null)
                {
                    ObjectFactory.Initialize(o => o.AddRegistry(new CommonRegistry()));
                    ObjectFactory.Configure(o => o.BuildInstancesOf<ILog>());
                    _logger = ObjectFactory.GetInstance<ILog>();
                }
                return _logger;
            }    

            set
            {
                _logger = value;
            }
        }

        /// <summary>
        /// Gets or sets the category of the current log.
        /// </summary>
        /// <value>The category.</value>
        public string Category { get; private set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="LogAttribute"/> class.
        /// </summary>
        /// <param name="category">The category.</param>
        public LogAttribute(string category)
        {
            this.Category = category;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LogAttribute"/> class.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <param name="logger">The logger.</param>
        public LogAttribute(string category, ILog logger) : this(category)
        {
            this.Logger = logger;   
        }

        /// <summary>
        /// Raises the <see cref="E:Entry"/> event.
        /// </summary>
        /// <param name="eventArgs">The <see cref="PostSharp.Laos.MethodExecutionEventArgs"/> instance containing the event data.</param>
        public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
            this.Logger.WriteMessage(string.Format("[Type:{0}] Entering {1}.{2}.", eventArgs.Method.DeclaringType.Name,
                                                   eventArgs.Method.Name, this.Category));
        }

        public override void OnExit(MethodExecutionEventArgs eventArgs)
        {
            this.Logger.WriteMessage(string.Format("[Type:{0}] Leaving {1}.{2}.", eventArgs.Method.DeclaringType.Name,
                                                   eventArgs.Method.Name, this.Category));
        }
    }
}
